package com.Example;
import com.Example.Model.Cert.CertInfo;
import com.Example.Model.Transfer.Transfer;
import com.Example.Model.SupplyType.IPTSignFixed;
import com.Example.Model.SupplyType.IPTSignShare;
import com.Example.Model.SupplyType.IPTSplit;
import com.Example.Model.SupplyType.ShareRatio;
import com.alibaba.fastjson.JSON;
import com.client.RepChainJksClient;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.JsonFormat;
import com.websocket.wsCallBack;
import org.apache.commons.io.FileUtils;
import com.alibaba.fastjson.JSONObject;
import com.protos.Peer.*;


import java.io.*;
import java.util.*;

import org.apache.commons.codec.binary.Hex;  // apache 的编码解码包

/**
 * 一些提交交易的例子，包括Invoke与deploy
 * @author zyf
 */
public class Commit implements wsCallBack {

    private static String host = "192.168.2.69:8081";
    private static RepChainJksClient client = new RepChainJksClient(host,"jks/121000005l35120456.node1.jks", "123", "121000005l35120456.node1");
    private static CertId certId = CertId.newBuilder().setCreditCode("121000005l35120456").setCertName("node1").build(); // 签名ID

    public static void main(String[] args) throws Exception{

        // 资产管理合约ID，此ID需要与repchain合约部署的一致
        ChaincodeId contractAssetsId = ChaincodeId.newBuilder().setChaincodeName("ContractAssetsTPL").setVersion(1).build();
        // 证书管理合约ID
        ChaincodeId contractCertId = ChaincodeId.newBuilder().setChaincodeName("ContractCertTPL").setVersion(1).build();
        // 分账合约ID
        ChaincodeId supplyTPLId = ChaincodeId.newBuilder().setChaincodeName("SupplyTPL").setVersion(1).build();


        // 构建转账交易
        String str_trans =  Files.asCharSource(new File("Json/transfer_1.json"), Charsets.UTF_8).read(); // google的包,最新的Files.toString()即将废弃
        Transaction transfer = client.createTransactionForInvoke(certId, contractAssetsId, "transfer" ,str_trans);
        String transferStr = Hex.encodeHexString(transfer.toByteArray());
        JSONObject transferResult = client.postTranByString(JSONObject.toJSONString(transferStr));

        // 构建转账交易2
        Transfer trans = new Transfer();  // 也可以直接用构造函数进行构造 new Transfer("st","st","int")
        trans.setFrom("12110107bi45jh675g");
        trans.setTo("122000002n00123567");
        trans.setAmount(5);
        Transaction transfer1 = client.createTransactionForInvoke(certId, contractAssetsId,"transfer" ,JSON.toJSONString(trans));
        //将交易数据post过去
        JSONObject transferResult2 = client.postTranByStream(transfer);
//        JSONObject transferResult = doPost("http://192.168.2.69:8081/transaction/postTranByString", '"'+transferStr+'"');

        // 注册账户
        ArrayList<String > CertNames = new ArrayList<>();
        CertNames.add("cert1");
        CertNames.add("cert2");
        Signer signer = Signer.newBuilder()
                .setName("zyf")
                .setCreditCode("121000005l35120567")
                .setMobile("13812345678")
                .addAllCertNames(CertNames)
                .build();
//        Map usrCer = new HashMap<String, String>();
//        usrCer.put(base64Cer, base64Info);
        Transaction signUpSigner = client.createTransactionForInvoke(certId, contractCertId, "SignUpSigner" ,JsonFormat.printer().print(signer));
        String signUpSignerStr = Hex.encodeHexString(signUpSigner.toByteArray());
        JSONObject signUpSignerResult = client.postTranByString(JSON.toJSONString(signUpSignerStr));


        //注册用户证书
        String pemCer = Files.asCharSource(new File("jks/qz.cer"), Charsets.UTF_8).read();
//      pemCrt = X509Factory.BEGIN_CERT + Base64.encodeBase64String(certificate.getEncoded()) + X509Factory.END_CERT;
        long regMillis = System.currentTimeMillis() + 8*3600*1000; //注册时间
        long unRegMillis = System.currentTimeMillis() + 2*8*3600*1000;  // 注销时间
        Timestamp regTime = Timestamp.newBuilder().setSeconds(regMillis/1000).setNanos((int)(regMillis % 1000) * 1000000).build();
        Timestamp unRegTime = Timestamp.newBuilder().setSeconds(unRegMillis/1000).setNanos((int)(unRegMillis % 1000) * 1000000).build();
        Certificate certificate = Certificate.newBuilder()
                .setCertificate(pemCer)
                .setAlgType("SHA1withECDSA")
                .setCertValid(true)
                .setRegTime(regTime)
                .setUnregTime(unRegTime)
                .build();
        CertInfo certInfo = new CertInfo("121000005l35120567","cert3", JSON.parse(JsonFormat.printer().print(certificate)));
        Transaction signUpCer = client.createTransactionForInvoke(certId, contractCertId, "SignUpCert" ,JSON.toJSONString(certInfo));
        String signUpCerStr = Hex.encodeHexString(signUpCer.toByteArray());
        JSONObject signUpCerResult = client.postTranByString(JSON.toJSONString(signUpCerStr));


        // 构建分账合约交易，并部署
        String str_supply = FileUtils.readFileToString(new File("Tpl/SupplyTPL.scala"), Charsets.UTF_8);  // apache commons的包
        Transaction SupplyTpl = client.createTransactionForDeploy(certId, supplyTPLId, str_supply, "", 5000, ChaincodeDeploy.CodeType.CODE_SCALA);
        String supplyTplstr = Hex.encodeHexString(SupplyTpl.toByteArray());
//        JSONObject tplDeployResult = client.postTranByString(JSON.toJSONString(supplyTplstr));  //   部署分账模板合约

        //调用分账合约
        String cname = SupplyTpl.getCid().getChaincodeName();
        Map<String,Double> fm = new HashMap<>();
        fm.put("A",0.2);
        fm.put("B",0.2);
        fm.put("C",0.1);
        fm.put("D",0.1);
        Map<String, ShareRatio[]> sm = new HashMap<>();
        ShareRatio[] shareRatios = new ShareRatio[]{new ShareRatio(0,100,0.1,0),new ShareRatio(100,10000,0.15,0)};
        sm.put("A",shareRatios);
        sm.put("B",new ShareRatio[]{new ShareRatio(0,10000,0,10)});
        sm.put("C",new ShareRatio[]{new ShareRatio(0,10000,0.1,0)});
        sm.put("D",new ShareRatio[]{new ShareRatio(0,100,0,10), new ShareRatio(100,10000,0.15,0)});
        String account_remain = "R";
        String account_sales1 = "S1";
        String account_sales2 = "S2";
        String product_id = "P201806270001";

        //构造签约交易合约模版1输入json字符串，销售1选择了合约模版1
        IPTSignFixed signfm = new IPTSignFixed(account_sales1,product_id,account_remain,fm);
        String signfmstr = JSONObject.toJSONString(signfm);//JSON.toJSONString(ipt2);

        //构造签约交易合约模版2输入json字符串，，销售2选择了合约模版2
        IPTSignShare signsm = new IPTSignShare(account_sales2,product_id,account_remain,sm);
        String signsmstr = JSON.toJSONString(signsm);
        Transaction signfmTran = client.createTransactionForInvoke(certId, supplyTPLId, "SignFixed", signfmstr);
        String fmTranstr = Hex.encodeHexString(signfmTran.toByteArray());

        // 部署模板1
        JSONObject signfmResult = client.postTranByString(JSON.toJSONString(fmTranstr));
        Transaction signsmTran = client.createTransactionForInvoke(certId, supplyTPLId, "SignShare", signsmstr);
        String smTranstr = Hex.encodeHexString(signsmTran.toByteArray());

        // 部署模板2
        JSONObject signsmResult = client.postTranByString(JSON.toJSONString(smTranstr));

        // 测试各种金额下的分账结果
        int[] sr = new int[]{100, 200, 500, 1000};
        for (int el:sr) {
            //构造分账交易
            IPTSplit ips1 = new IPTSplit(account_sales1,product_id,el);
            IPTSplit ips2 = new IPTSplit(account_sales2,product_id,el);
            String l4 = JSON.toJSONString(ips1);
            String l5 = JSON.toJSONString(ips2);
            //调用模板1进行分账
            Transaction s1Split = client.createTransactionForInvoke(certId, supplyTPLId,"Split", l4);
            //调用模板2进行分账
            Transaction s2Split = client.createTransactionForInvoke(certId, supplyTPLId, "Split", l5);
            String s1Splitstr = Hex.encodeHexString(s1Split.toByteArray());
            String s2Splitstr = Hex.encodeHexString(s2Split.toByteArray());
            //  提交交易
            JSONObject s1SplitResult = client.postTranByString(JSON.toJSONString(s1Splitstr));
//              JSONObject s2SplitResult = client.postTranByString(JSON.toJSONString(s2Splitstr));
            // 下面是用来测试回调方法的
            client.postTranByString(new Commit(), JSON.toJSONString(s2Splitstr), s2Split);
        }

    }

    /**
     *
     * @param flag
     * @param result 预执行结果
     */
    @Override
    public void preDoTransaction(Boolean flag, JSONObject result) {
        System.out.println(result);
    }

    /**
     *
     * @param flag
     * @param block
     * @param result
     */
    @Override
    public void verifyBlock(Boolean flag, Block block, String result) {
        System.out.println(block);
        System.out.println(result);
    }

    @Override
    public void onChain(String txid, Boolean result) {
        System.out.println("############");
        if (result) {
            System.out.println("已经确认出块,交易id：" + txid);
            System.out.println("交易ID为：" + txid);
            //todo 添加交易入块的标志到数据库

        } else {
            System.out.println("未知错误，未入块，交易id：" + txid);
        }
        System.out.println("############");
    }
}
